home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
demos
/
video
/
specialfx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
28KB
|
1,000 lines
/*
* Copyright (C) 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
* specialfx.c: video effects demonstration program
*
* - primarily for Galileo and IndyVideo
*
* This program uses most of the VL example,
* 'simpleblend.c'
*
*
* Notes:
* modified 12/01/93 a.tang
* modified 12/17/93 a.tang 'port' from nov15 to dec15 VL
* modified 1/27/94 a.tang 'port' to 5.2 VL (images.Jan27)
* add PAL support
*
* some of this code is generated by:
* Builder Xcessory 3.0 FT. (a UI builder)
*
*/
#include "specialfx.h"
#include <X11/keysym.h>
float Version_number = 2.0; /* version number */
XSizeHints sizehints; /* for window placement and size */
Boolean gfxonvid = True;/* for handling fg/bg */
XtAppContext theAppcontext; /* for event processing */
Display *UIdisplay; /* global UI event processing */
void myprocessXEvent(); /* process UI X events */
void VideoTracking(Window, int,int);
void processXEvent(uint, void *);
void processVLEvent(VLServer, VLEvent *, void *);
void docleanup(void);
void usage(void);
void doErrorExit(char *s);
VLServer vlSvr = NULL;
VLPath vlPath = -1;
VLDevList devlist;
VLNode src_vid;
VLNode src_scr;
VLNode drn_scr;
VLNode drn_vid;
VLNode blend_node;
VLNode mydev_node;
Display *dpy;
Window srcwin;
Window drnwin;
Window vidinwin;
int vout = VL_ANY;
int vin = VL_ANY;
int vinflag = 0;
int voutflag = 0;
char *_progname;
char *deviceName;
int devicenum = -1;
int debug = 0;
int ver = 0;
int input_timing;
int print_ids = 0;
Boolean zoomdown = False;
int fullx, fully;
Atom WM_DELETE_WINDOW;
Atom WM_PROTOCOLS;
int lastw = 0, lasth = 0;
#define Debug if (debug) printf
#define fDebug if (debug) fprintf
#define checkSetControlReturn(ret) \
if (ret != VLSuccess && vlErrno != VLValueOutOfRange) \
doErrorExit("vlSetControl");
#define SCR_XMAX 1280
#define SCR_YMAX 1024
/* blend window bottom left, gfx-in window upper left: */
#define DEFAULT_BLEND_X 10
#define DEFAULT_BLEND_Y_NTSC 490 /* upper edge */
#define DEFAULT_BLEND_Y_PAL 587 /* upper edge */
#define DEFAULT_GFX_SRC_X 0
#define DEFAULT_GFX_SRC_Y 0
/* blend window upper left, gfx-in window bottom left: */
/*
#define DEFAULT_BLEND_X 10
#define DEFAULT_BLEND_Y 10
#define DEFAULT_GFX_SRC_X 10
#define DEFAULT_GFX_SRC_Y 530
*/
#define ESC_KEY '\006'
#define USAGE \
"%s: [-f] [-n <devicenum>] [-d] [-v <videonode>] [-o <videonode> ] [-z]\
\n\
\t-f\tdisable forking\n\
\t-n\tdevice number to use\n\
\t-d\tdebug mode\n\
\t-v\tvideo input source to use (depends on hardware)\n\
\t-o\tvideo output source to use (depends on hardware)\n\
\t-z\tzoom down the video windows by one-half.\n\
\t-h\tthis help message\n"
/* Constrain the window's aspect ratio */
void
constrainWindowResize(Display *dpy, Window win, int max_w, int max_h)
{
XSizeHints xsh;
xsh.min_aspect.x = xsh.max_aspect.x = 80;
xsh.min_aspect.y = xsh.max_aspect.y = 60;
xsh.min_width = max_w;
xsh.min_height = max_h;
xsh.max_width = max_w;
xsh.max_height = max_h;
xsh.flags = PAspect|PMinSize|PMaxSize;
XSetWMNormalHints(dpy, win, &xsh);
XResizeWindow(dpy, win, max_w, max_h);
}
/*
* Error reporting and program cleanup routine
*/
void
doErrorExit(char *s)
{
char foo[80];
sprintf(foo,"%s(%s)", _progname, s);
vlPerror(foo);
docleanup();
}
void
initBlendControls()
{
VLControlValue vlctlval;
vlctlval.intVal = 0;
vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_DETAIL,&vlctlval);
vlctlval.intVal = 5;
vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_VALUE_CHROMA_U,&vlctlval);
vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_VALUE_CHROMA_V,&vlctlval);
vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_VALUE_LUMA,&vlctlval);
vlctlval.intVal = 5;
vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_RANGE_CHROMA_U,&vlctlval);
vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_RANGE_CHROMA_V,&vlctlval);
vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_RANGE_LUMA,&vlctlval);
vlctlval.intVal = 255;
vlSetControl(vlSvr,vlPath,blend_node,VL_EV1_KEYER_FG_OPACITY,&vlctlval);
}
void
usage()
{
fprintf(stderr, USAGE, _progname);
}
/*
* Main Program.
*/
main(argc, argv)
int argc;
char **argv;
{
Arg args[256];
Cardinal argcnt;
Boolean argok;
char *winname = NULL;
int opterr = 0;
int c, i;
int dev;
int ret;
int nofork = 0;
int x, y;
Atom WM_PROT_SET[2];
Atom _SGI_VIDEO;
VLControlValue val;
VLControlValue myval;
int zero = 0;
int usehints = 1; /* for size hints */
_progname = argv[0];
/*
* Parse command line options
* -f disable forking
* -n device number
* -d set debugging
* -z zoom down video windows 1/2
* -h display help message
*/
while ((c = getopt(argc, argv, "dv:o:n:Ifzh")) != EOF)
{
switch(c)
{
case 'f':
nofork = 1;
break;
case 'n':
devicenum = atoi(optarg);
printf("User specified device:%d\n", devicenum);
break;
case 'd':
debug++;
break;
case 'I':
print_ids = 1;
break;
case 'v':
vin = atoi(optarg);
vinflag = 1;
Debug ("video input = %d\n", vin);
break;
case 'o':
vout = atoi(optarg);
voutflag = 1;
Debug ("video output = %d\n", vout);
break;
case 'z':
zoomdown = True;
break;
case 'h':
usage();
exit(0);
break;
}
}
if (opterr)
{
usage();
exit(1);
}
XtToolkitInitialize();
theAppcontext = XtCreateApplicationContext();
UIdisplay = XtOpenDisplay(theAppcontext, 0, BX_APP_NAME, BX_APP_CLASS,
0, 0, &zero, argv);
/*
#ifndef XtSpecificationRelease
0, 0, (Cardinal*)&myargc, myargv);
#else
#if XtSpecificationRelease == 4
0, 0, (Cardinal*)&myargc, myargv);
#else
0, 0, &myargc, myargv);
#endif
#endif
*/
if(UIdisplay == NULL)
{
XtWarning("cannot open display");
exit(1);
}
/*
* So converters work.
*/
XtInitializeWidgetClass(applicationShellWidgetClass);
/*
* Register special BuilderXcessory converters.
*/
RegisterBxConverters(theAppcontext);
/* Run in background if no-forking option not set */
if (!nofork)
{
ret = fork();
switch (ret)
{
case 0:
break;
case -1:
fprintf(stderr, "%s: can't fork\n");
exit(1);
break;
default:
exit(0);
break;
}
}
/* Connect to the daemon */
if (!(vlSvr = vlOpenVideo("")))
{
printf("%s: opening video: %s\n",_progname,vlStrError(vlErrno));
exit(1);
}
/* Get the list of devices the daemon supports */
if (vlGetDeviceList(vlSvr, &devlist) < 0)
{
printf("%s: getting device list: %s\n",_progname,vlStrError(vlErrno));
exit(1);
}
/* Make sure that the device the user requested (if any) is in the list */
if ((devicenum >= (int)devlist.numDevices) || (devicenum < -1))
{
if (devlist.numDevices == 1)
fprintf(stderr,"%s: The device number must be 0\n",_progname);
else
fprintf(stderr,"%s: The device number must be between 0 and %d\n",
_progname, devlist.numDevices-1);
exit(1);
}
/* find ev1 */
for (i=0; i<devlist.numDevices; i++)
if (strcmp(devlist.devices[i].name,"ev1") == 0)
ev1num = i;
if ( (ev1num == -1) /* no ev1 found ... OR ...*/
|| ((devicenum != -1) && (devicenum != ev1num))) /* non ev1 specified*/
{
printf("This program requires 'ev1' hardware.\a\n");
if (ev1num != -1)
printf("Use device number '%d', or use the default mode\n",ev1num);
exit(1);
}else
{
printf("Setting device number to %d\n", ev1num);
devicenum = ev1num; /* allow default to work */
}
/*
* Establish a path between the screen source and video
* drain. Then add a video source node and a screen drain
* node.
*/
/* Setup drain nodes on the screen and video */
drn_scr = vlGetNode(vlSvr, VL_DRN, VL_SCREEN, VL_ANY);
if (voutflag == 0)
drn_vid = vlGetNode(vlSvr, VL_DRN, VL_VIDEO, VL_ANY);
else
drn_vid = vlGetNode(vlSvr, VL_DRN, VL_VIDEO, vout);
/* Setup source nodes on the screen and video */
src_scr = vlGetNode(vlSvr, VL_SRC, VL_SCREEN, VL_ANY);
if (vinflag == 0)
src_vid = vlGetNode(vlSvr, VL_SRC, VL_VIDEO, VL_ANY);
else
src_vid = vlGetNode(vlSvr, VL_SRC, VL_VIDEO, vin);
mydev_node = vlGetNode(vlSvr, VL_DEVICE, 0,VL_ANY);
if (mydev_node < 0)
{
printf("get device node error\n");
vlPerror(_progname);
exit(1);
}
blend_node = vlGetNode(vlSvr, VL_INTERNAL, VL_BLENDER, VL_ANY);
if (blend_node < 0)
{
printf("get blend node error\n");
vlPerror(_progname);
exit(1);
}
vlPath = -1;
/* If no device was specified... */
if (devicenum == -1)
{
/* Try to create the screen to video path */
vlPath = vlCreatePath(vlSvr, VL_ANY, src_scr, drn_vid);
/* Add the video source and screen drain nodes */
ret = vlAddNode(vlSvr, vlPath, src_vid);
if (!ret)
{
ret = vlAddNode(vlSvr, vlPath, drn_scr);
}
if (ret)
{ /* Device doesn't support this path, these nodes */
vlDestroyPath(vlSvr, vlPath);
vlPath = -1;
}
else
{ /* Path OK, get device info */
devicenum = vlGetDevice(vlSvr, vlPath);
deviceName = devlist.devices[devicenum].name;
}
}
else /* User specified a device */
{ /* Get the device info */
deviceName = devlist.devices[devicenum].name;
/* Try to create the screen to video path */
vlPath = vlCreatePath(vlSvr, devicenum, src_scr, drn_vid);
/* Add the video source and screen drain nodes */
ret = vlAddNode(vlSvr, vlPath, src_vid);
if (!ret)
{
ret = vlAddNode(vlSvr, vlPath, drn_scr);
}
if (ret)
{ /* Device doesn't support this path, these nodes */
vlDestroyPath(vlSvr, vlPath);
vlPath = -1;
}
}
if (vlAddNode(vlSvr, vlPath, mydev_node))
{
vlPerror("Add Device Node");
vlDestroyPath(vlSvr, vlPath);
vlPath = -1;
}
if (vlAddNode(vlSvr, vlPath, blend_node))
{
vlPerror("Add Blend Node");
vlDestroyPath(vlSvr, vlPath);
vlPath = -1;
}
if (vlPath == -1)
{ /* Couldn't create the path, quit */
vlPerror("Path Setup");
docleanup();
}
/* Set up the hardware for and define the usage of the path */
if (vlSetupPaths(vlSvr,(VLPathList)&vlPath,1,VL_SHARE,VL_READ_ONLY)<0)
{
printf("setup paths error\n");
vlPerror(_progname);
exit(1);
}
/* initialize to ev1 slave mode. */
vlGetControl(vlSvr, vlPath, mydev_node, VL_SYNC, &val);
#ifdef DEBUG
printf("\n");
printf("initial sync value = %d\n", val.intVal);
printf("ev1 value = %d\n", VL_EV1_SYNC_SLAVE);
#endif
/* set to slave mode */
val.intVal = VL_EV1_SYNC_SLAVE;
if (vlSetControl(vlSvr, vlPath, mydev_node, VL_SYNC, &val) < 0)
{
printf("set sync mode error\n");
vlPerror(_progname);
exit(1);
}
vlGetControl(vlSvr, vlPath, mydev_node, VL_SYNC, &val);
#ifdef DEBUG
printf ("after set value, sync val = %d\n", val.intVal);
#endif
/* get the current input timing */
vlGetControl(vlSvr, vlPath, src_vid, VL_TIMING, &val);
input_timing = val.intVal;
/* Get the current size of the drain window */
vlGetControl(vlSvr, vlPath, drn_scr, VL_SIZE, &val);
fullx = lastw = val.xyVal.x;
fully = lasth = val.xyVal.y;
Debug("fullx,fully = %d,%d\n", fullx,fully);
/* for drnwin (blend output): zoom 1/2 if non 525 */
if ((input_timing == VL_TIMING_625_SQ_PIX) ||
(input_timing == VL_TIMING_625_CCIR601) ||
(input_timing == VL_TIMING_625_4FSC))
{
Debug("non 525 timing detected\n");
if (lasth != 576) lasth = 576;
zoomdown = True;
}
if (zoomdown)
{
val.fractVal.numerator = 1;
val.fractVal.denominator = 2;
if (vlSetControl(vlSvr, vlPath, drn_scr, VL_ZOOM, &val)<0)
vlPerror("WARNING: set zoom error\n");
val.xyVal.x = fullx; /* set val.xyVal.x to full size */
val.xyVal.y = fully; /* set val.xyVal.y to full size */
if (vlSetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val)<0)
vlPerror("WARNING: set size error\n");
vlGetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val);
/* now set lastw and lasth to the drain size again */
lastw = lastw/2; /* to go with zoom 1/2 */
lasth = lasth/2; /* to go with zoom 1/2 */
}
/* Set the source to the full size */
val.xyVal.x = fullx;
val.xyVal.y = fully;
Debug("setting source VLSIZE to = %d,%d\n", val.xyVal.x,val.xyVal.y);
if ( vlSetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val)!= 0)
{
printf("set vlsize error\n");
vlPerror(_progname);
exit(1);
}
/* Make sure there's enough room for a source window of the same size */
vlGetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val);
#ifdef oldcode
if (((val.xyVal.x+lastw)>SCR_XMAX) || ((val.xyVal.y+lasth)>SCR_YMAX))
#endif
if ((val.xyVal.y+lasth)>SCR_YMAX)
{
printf("%s: unable to make two full size windows\n", _progname);
docleanup();
}
/* Set the keyer mode, keyer source and blend controls */
val.intVal = VL_EV1_KEYERMODE_LUMA;
if (vlSetControl(vlSvr, vlPath, blend_node, VL_EV1_KEYER_MODE, &val)<0)
{
printf("set keyer mode error\n");
vlPerror(_progname);
exit(1);
}
val.intVal = src_scr;
/*
if (vlSetControl(vlSvr, vlPath, blend_node, VL_EV1_KEYER_SOURCE, &val)<0)
{
printf("set keyer source error\n");
vlPerror(_progname);
exit(1);
}
*/
val.intVal = src_scr;
if (vlSetControl(vlSvr, vlPath, blend_node, VL_BLEND_A, &val)!=0)
{
printf("set blend A error\n");
vlPerror(_progname);
exit(1);
}
val.intVal = src_vid;
if (vlSetControl(vlSvr, vlPath, blend_node, VL_BLEND_B, &val)!=0)
{
printf("set blend B error\n");
vlPerror(_progname);
exit(1);
}
/* open a display */
if (!(dpy = XOpenDisplay("")))
{
printf("%s: can't open display\n", _progname);
exit(1);
}
/* create the source window to be the full size */
srcwin = XCreateWindow(dpy, RootWindow(dpy, 0),
DEFAULT_GFX_SRC_X, DEFAULT_GFX_SRC_Y,
fullx, fully, 0,
CopyFromParent, CopyFromParent, CopyFromParent,
(ulong) 0, NULL);
drnwin = XCreateWindow(dpy, RootWindow(dpy, 0),
DEFAULT_BLEND_X, DEFAULT_BLEND_Y_PAL,
lastw, lasth, 0,
CopyFromParent, CopyFromParent, CopyFromParent,
(ulong) 0, NULL);
_SGI_VIDEO = XInternAtom(dpy, "_SGI_VIDEO", False);
WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
WM_PROTOCOLS = XInternAtom(dpy, "WM_PROTOCOLS", False);
WM_PROT_SET[0] = WM_DELETE_WINDOW;
WM_PROT_SET[1] = _SGI_VIDEO;
XSetWMProtocols(dpy,drnwin, WM_PROT_SET, 2);
XSetWMProtocols(dpy,srcwin, WM_PROT_SET, 2);
XStoreName(dpy, srcwin, "Video Blending Source");
XStoreName(dpy, drnwin, "Video Blending");
/* Adjust source window's aspect ratio *//* not needed - not managed */
/* constrainWindowResize(dpy, srcwin, lastw, lasth); */
/* Turn off the source window's border *//* not needed - not managed */
/* noborders(dpy, srcwin); */
/* Adjust the drain window's aspect ratio */
constrainWindowResize(dpy, drnwin, lastw, lasth);
/* Set the video to appear in window drnwin */
val.intVal = drnwin;
if (vlSetControl(vlSvr, vlPath, drn_scr, VL_WINDOW, &val)<0)
vlPerror("WARNING: set VL_WINDOW error\n");
/* Make sure there's room for both the source and drain window */
vlGetControl(vlSvr, vlPath, drn_scr, VL_SIZE, &val);
#ifdef oldcode
if (((val.xyVal.x+lastw)>SCR_XMAX) || ((val.xyVal.y+lasth)>SCR_YMAX))
#endif
if ((val.xyVal.y+lasth)>SCR_YMAX)
{
printf("%s: unable to make two full size windows\n", _progname);
docleanup();
}
vlGetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val);
#ifdef oldcode
if (((val.xyVal.x+lastw)>SCR_XMAX) || ((val.xyVal.y+lasth)>SCR_YMAX))
#endif
if ((val.xyVal.y+lasth)>SCR_YMAX)
{
printf("%s: unable to make two full size windows\n", _progname);
docleanup();
}
/* Get the location of the screen source */
vlGetControl(vlSvr, vlPath, src_scr, VL_ORIGIN, &val);
/* Set the controls for the location of the src_scr node: */
/* note: doing it before this point, we seem to lose the setting */
myval.xyVal.x = DEFAULT_GFX_SRC_X;
myval.xyVal.y = DEFAULT_GFX_SRC_Y;
if(vlSetControl(vlSvr, vlPath, src_scr, VL_ORIGIN, &myval)<0)
vlPerror("WARNING: set VL_ORIGIN error\n");
vlGetControl(vlSvr, vlPath, src_scr, VL_ORIGIN, &val);
/* Print the node and path IDs for cmd line users */
if (print_ids)
{
printf("SPECIALFX NODE IDs:\n");
printf("screen source = %d\n", src_scr);
printf("video source = %d\n", src_vid);
printf("screen drain = %d\n", drn_scr);
printf("video drain = %d\n", drn_vid);
printf("device = %d\n", mydev_node);
printf("blend = %d\n", blend_node);
printf("PATH ID = %d\n", vlPath);
}
/* set up size and placement hint info */
sizehints.x = DEFAULT_BLEND_X;
if ((input_timing == VL_TIMING_625_SQ_PIX) ||
(input_timing == VL_TIMING_625_CCIR601) ||
(input_timing == VL_TIMING_625_4FSC))
{
sizehints.y = DEFAULT_BLEND_Y_PAL;
}else
{
sizehints.y = DEFAULT_BLEND_Y_NTSC;
}
if (usehints) {
bzero(&sizehints, sizeof(XSizeHints));
sizehints.base_width = 640;
sizehints.base_height = 486;
sizehints.min_width = sizehints.max_width = sizehints.base_width;
sizehints.min_height = sizehints.max_height = sizehints.base_height;
sizehints.flags = USPosition;
XSetWMNormalHints(dpy, drnwin, &sizehints);
}
val.xyVal.x = sizehints.x;
val.xyVal.y = sizehints.y;
Debug("setting screen drain origin to: %d %d\n", val.xyVal.x, val.xyVal.y);
if (vlSetControl(vlSvr, vlPath, drn_scr, VL_ORIGIN, &val)<0)
vlPerror("WARNING: set drn origin error\n");
if (vlGetControl(vlSvr, vlPath, drn_scr, VL_ORIGIN, &val)<0)
vlPerror("WARNING: get drn origin error\n");
Debug("got screen drain origin: %d %d\n", val.xyVal.x, val.xyVal.y);
if (vlGetControl(vlSvr, vlPath, drn_scr, VL_SIZE, &val)<0)
vlPerror("WARNING: get drn origin error\n");
Debug("got screen drain size: %d %d\n", val.xyVal.x, val.xyVal.y);
XMapWindow(dpy, drnwin);
/* Set up the hardware for and define the usage of the path */
if (vlSetupPaths(vlSvr, (VLPathList)&vlPath, 1, VL_SHARE, VL_SHARE) < 0)
{
printf("setup paths error\n");
vlPerror(_progname);
exit(1);
}
/* reset zoomdown now, after the SHARE SHARE vlSetupPaths */
if (zoomdown)
{
Debug("Zooming down...\n");
val.fractVal.numerator = 1;
val.fractVal.denominator = 2;
if (vlSetControl(vlSvr, vlPath, drn_scr, VL_ZOOM, &val)<0)
vlPerror("WARNING: set zoom error\n");
val.xyVal.x = fullx/2;
val.xyVal.y = fully/2;
if (vlSetControl(vlSvr, vlPath, drn_scr, VL_SIZE, &val)<0)
vlPerror("WARNING: set size error\n");
XResizeWindow(dpy, drnwin, val.xyVal.x, val.xyVal.y);
XSync(dpy, 0);
XSync(dpy, 0);
val.xyVal.x = fullx; /* set val.xyVal.x to full size */
val.xyVal.y = fully; /* set val.xyVal.y to full size */
if (vlSetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val)<0)
vlPerror("WARNING: set size error\n");
vlGetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val);
}
/* Set screen source origin and size now after vlSetupPaths */
Debug("screen source origin: %d %d\n", val.xyVal.x, val.xyVal.y);
myval.xyVal.x = fullx;
myval.xyVal.y = fully;
if (vlSetControl(vlSvr, vlPath, src_scr, VL_SIZE, &myval)<0)
vlPerror("WARNING: set size error\n");
vlGetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val);
Debug("Gotton screen source size: %d %d\n", val.xyVal.x, val.xyVal.y);
XSelectInput(dpy, drnwin, KeyPressMask|VisibilityChangeMask
|ExposureMask|StructureNotifyMask);
XSync(dpy, 0);
initBlendControls();
/* ------ start build UI widgets ------ */
/*
* The applicationShell is created as an unrealized
* parent for multiple topLevelShells. The topLevelShells
* are created as popup children of the applicationShell.
* This is a recommendation of Paul Asente & Ralph Swick in
* _X_Window_System_Toolkit_ p. 677.
*/
argcnt = 0;
AppShell = XtAppCreateShell( BX_APP_NAME, BX_APP_CLASS,
applicationShellWidgetClass, UIdisplay, args, argcnt);
XtInitializeWidgetClass(topLevelShellWidgetClass);
argcnt = 0;
XtSetArg(args[argcnt], XmNkeyboardFocusPolicy, XmPOINTER); argcnt++;
XtSetArg(args[argcnt], XmNx, 450); argcnt++;
XtSetArg(args[argcnt], XmNy, 487); argcnt++;
Shell000 = XtCreatePopupShell( "topLevelShell",
topLevelShellWidgetClass, AppShell, args, argcnt);
MainWindow = CreatemainWindow(Shell000);
Shell001 = CreatechromaShell(AppShell);
ChromaBBoard = CreatechromaBBoard(Shell001);
Shell002 = CreatelumaShell(AppShell);
LumaBBoard = CreatelumaBBoard(Shell002);
Shell003 = CreateswitchShell(AppShell);
SwitchBBoard = CreateswitchBBoard(Shell003);
XtManageChild(MainWindow);
XtPopup(XtParent(MainWindow), XtGrabNone);
/* ------ end build UI widgets ----- */
/* Specify a file descriptor and pending check function for VL events */
vlRegisterHandler(vlSvr, ConnectionNumber(dpy), processXEvent,
(VLPendingFunc)XPending, dpy);
/* Now, my UI X events */
vlRegisterHandler(vlSvr, ConnectionNumber(UIdisplay), myprocessXEvent,
(VLPendingFunc)XPending, UIdisplay);
/* Set up event handler routine as callback for all events */
vlAddCallback(vlSvr, vlPath, VLAllEventsMask, processVLEvent, NULL);
/* Start the data transfer immediately (i.e. don't wait for trigger) */
vlBeginTransfer(vlSvr, vlPath, 0, NULL);
vlMainLoop();
} /* end main */
/*
* VideoTracking - if the user changes the size of the window,
* update the video to reflect the new size and position.
*/
void
VideoTracking(Window win, int x, int y)
{
Window dummyWin;
VLControlValue val;
/* Get X's idea of origin */
XTranslateCoordinates(dpy, win, RootWindow(dpy, DefaultScreen(dpy)),
0, 0,
&x, &y,
&dummyWin);
/* Try to make vl match X */
val.xyVal.x = x;
val.xyVal.y = y;
if (win == drnwin)
vlSetControl(vlSvr, vlPath, drn_scr, VL_ORIGIN, &val);
else
vlSetControl(vlSvr, vlPath, src_scr, VL_ORIGIN, &val);
}
/*
* VLEvent processing for video to screen.
* We only deal with control changed events.
*/
void
processVLEvent(VLServer vlSvr, VLEvent *ev, void *dummy)
{
VLControlChangedEvent *cev = (VLControlChangedEvent *) ev;
VLControlValue val;
Debug("VL event.type = %d\n", ev->reason);
switch (ev->reason)
{ /* Ignore all but a change in the drain's location */
case VLControlChanged:
if (cev->type == VL_ORIGIN)
{
if (cev->node == drn_scr)
{ /* Drain moved, move window accordingly */
vlGetControl(vlSvr, vlPath, drn_scr, VL_ORIGIN, &val);
XMoveWindow(dpy, drnwin, val.xyVal.x, val.xyVal.y);
}
else if (cev->node == src_scr)
{ /* Source moved, move window accordingly */
vlGetControl(vlSvr, vlPath, src_scr, VL_ORIGIN, &val);
XMoveWindow(dpy, srcwin, val.xyVal.x, val.xyVal.y);
}
}
break;
}
}
/* my XEvent processing for UI */
void
myprocessXEvent()
{
XEvent event;
/* do the XtAppMainLoop next and dispatch here */
XtAppNextEvent(theAppcontext, &event);
/* got an XtAppNextEvent */
XtDispatchEvent(&event);
}
/* XEvent processing for video to screen */
void
processXEvent(uint fd, void *source)
{
int ret,i;
XEvent event;
VLControlValue val;
VLControlValue myval;
if (source == (caddr_t)dpy)
{
XEvent ev;
XNextEvent(dpy, &ev);
switch (ev.type)
{
case ClientMessage:
if (ev.xclient.message_type == WM_PROTOCOLS)
if (ev.xclient.data.l[0] == WM_DELETE_WINDOW)
docleanup();
break;
case Expose: /* These really don't effect us */
case GraphicsExpose:
case VisibilityNotify:
break;
case ConfigureNotify: /* Window moved or changed size */
VideoTracking(ev.xany.window, ev.xconfigure.x,ev.xconfigure.y);
break;
case KeyPress:
{
XKeyEvent *kev = (XKeyEvent *)&ev;
KeySym keysym;
char buf[4];
XLookupString(kev, buf, 1, &keysym, 0);
switch (keysym)
{
/* Pan right */
case XK_Left:
/* Get current offset */
if (vlGetControl(vlSvr,vlPath,drn_scr,VL_OFFSET,&val))
doErrorExit("get offset");
val.xyVal.x++;
ret = vlSetControl(vlSvr,vlPath,drn_scr, VL_OFFSET, &val);
/* Make sure offset is OK */
checkSetControlReturn(ret);
break;
/* Pan left */
case XK_Right:
/* Get current offset */
if (vlGetControl(vlSvr,vlPath,drn_scr,VL_OFFSET,&val))
doErrorExit("get offset");
val.xyVal.x--;
ret = vlSetControl(vlSvr,vlPath,drn_scr, VL_OFFSET, &val);
/* Make sure offset is OK */
checkSetControlReturn(ret);
break;
/* Pan up */
case XK_Down:
/* Get current offset */
if (vlGetControl(vlSvr,vlPath,drn_scr,VL_OFFSET,&val))
doErrorExit("get offset");
val.xyVal.y--;
ret = vlSetControl(vlSvr,vlPath,drn_scr, VL_OFFSET, &val);
/* Make sure offset is OK */
checkSetControlReturn(ret);
break;
/* Pan down */
case XK_Up:
/* Get current offset */
if (vlGetControl(vlSvr,vlPath,drn_scr,VL_OFFSET,&val))
doErrorExit("get offset");
val.xyVal.y++;
ret = vlSetControl(vlSvr,vlPath,drn_scr, VL_OFFSET, &val);
/* Make sure offset is OK */
checkSetControlReturn(ret);
break;
}
switch (buf[0])
{
case '+':
val.fractVal.numerator = 1;
val.fractVal.denominator = 1;
if (vlSetControl(vlSvr, vlPath, \
drn_scr, VL_ZOOM, &val)<0)
vlPerror("WARNING: set zoom error\n");
val.xyVal.x = fullx;
val.xyVal.y = fully;
if (vlSetControl(vlSvr, vlPath, \
drn_scr, VL_SIZE, &val)<0)
vlPerror("WARNING: set size error\n");
XResizeWindow(dpy, drnwin, val.xyVal.x, val.xyVal.y);
XSync(dpy, 0);
XSync(dpy, 0);
break;
case '-':
val.fractVal.numerator = 1;
val.fractVal.denominator = 2;
if (vlSetControl(vlSvr, vlPath, \
drn_scr, VL_ZOOM, &val)<0)
vlPerror("WARNING: set zoom error\n");
val.xyVal.x = fullx/2;
val.xyVal.y = fully/2;
if (vlSetControl(vlSvr, vlPath, \
drn_scr, VL_SIZE, &val)<0)
vlPerror("WARNING: set size error\n");
XResizeWindow(dpy, drnwin, val.xyVal.x, val.xyVal.y);
XSync(dpy, 0);
XSync(dpy, 0);
break;
/* Quit */
case 'q':
case 'Q':
case ESC_KEY:
docleanup();
break;
default:
break;
}
}
}
} /* end if source == dpy */
}
/* Dispose of the vl structures */
void
docleanup(void)
{ /* End the data transfer */
vlEndTransfer(vlSvr, vlPath);
/* Destroy the path, free it's memory */
vlDestroyPath(vlSvr, vlPath);
/* Disonnect from the daemon */
vlCloseVideo(vlSvr);
exit(0);
}